#include "stdafx.h"
#include "ResourceManager.h"
#include "Shader.h"
#include "Model.h"
#include "Texture.h"
#include "Utils.h"

cResourceManager* cResourceManager::ms_Instance = NULL;

cResourceManager::~cResourceManager()
{
	for (unsigned int i = 0; i < m_vShaders.size(); i++)
	{
		SAFE_DEL(m_vShaders[i]);
	}
	m_vShaders.clear();

	for (unsigned int i = 0; i < m_vModels.size(); i++)
	{
		SAFE_DEL(m_vModels[i]);
	}
	m_vModels.clear();


	for (unsigned int i = 0; i < m_vTextures.size(); i++)
	{
		SAFE_DEL(m_vTextures[i]);
	}
	m_vTextures.clear();
}

cResourceManager* cResourceManager::GetInstance()
{
	if (ms_Instance == NULL)
	{
		ms_Instance = new cResourceManager();
	}
	return ms_Instance;
}

void cResourceManager::DestroyInstance()
{
	SAFE_DEL(ms_Instance);
}

void cResourceManager::LoadResource(const char *file_url)
{
	FILE		*pFile;
	char		buffer[MAX_LENGTH];
	char		scan_buffer[MAX_LENGTH];
	int			iStart;
	bool		hasReadData = false;
	cShader		*pShader;
	cModel		*pModel;
	cTexture	*pTexture;

	memset(buffer, '\0', MAX_LENGTH);
	memset(scan_buffer, '\0', MAX_LENGTH);

	fopen_s(&pFile, file_url, "r");

	while (!feof(pFile))
	{
		if (!hasReadData)
		{
			ReadLine(pFile, buffer);
			ScanString(buffer, scan_buffer);
		}
		else
		{
			hasReadData = false;
		}

		if (_strcmpi(scan_buffer, "#Shaders") == 0)
		{
			hasReadData = true;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "ID") == 0)
				{
					pShader = new cShader();
					m_vShaders.push_back(pShader);

					ScanNumberInt32(buffer, &pShader->m_ID, iStart);
				}
				else if (_strcmpi(scan_buffer, "FILE") == 0)
				{
					iStart = ScanString(buffer, pShader->m_fileVertexShader, iStart);
					ScanString(buffer, pShader->m_fileFragmentShader, iStart);
				}
				else if (_strcmpi(scan_buffer, "CULL") == 0)
				{
					ScanString(buffer, scan_buffer, iStart);
					if (_strcmpi(scan_buffer, "TRUE") == 0)
						pShader->m_state |= STATE_CULL;
					else
						pShader->m_state &= ~STATE_CULL;
				}
				else if (_strcmpi(scan_buffer, "DEPTH") == 0)
				{
					ScanString(buffer, scan_buffer, iStart);
					if (_strcmpi(scan_buffer, "TRUE") == 0)
						pShader->m_state |= STATE_DEPTH;
					else
						pShader->m_state &= ~STATE_DEPTH;
				}
				else if (_strcmpi(scan_buffer, "ALPHA") == 0)
				{
					ScanString(buffer, scan_buffer, iStart);
					if (_strcmpi(scan_buffer, "TRUE") == 0)
						pShader->m_state |= STATE_ALPHA;
					else
						pShader->m_state &= ~STATE_ALPHA;
				}
			}
		}

		if (_strcmpi(scan_buffer, "#Models") == 0)
		{
			hasReadData = true;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "ID") == 0)
				{
					pModel = new cModel();
					m_vModels.push_back(pModel);

					ScanNumberInt32(buffer, &pModel->m_ID, iStart);
				}
				else if (_strcmpi(scan_buffer, "FILE") == 0)
				{
					ScanString(buffer, pModel->m_fileModel, iStart);
				}
			}
		}

		if (_strcmpi(scan_buffer, "#Textures") == 0)
		{
			hasReadData = true;
			int index = 0;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "ID") == 0)
				{
					pTexture = new cTexture();
					m_vTextures.push_back(pTexture);

					index = 0;
					ScanNumberInt32(buffer, &pTexture->m_ID, iStart);
				}
				else if (_strcmpi(scan_buffer, "TYPE") == 0)
				{
					ScanString(buffer, scan_buffer, iStart);
					if (_strcmpi(scan_buffer, "CUBE") != 0)
						pTexture->m_type = cTexture::TEXTURE_2D;
					else
						pTexture->m_type = cTexture::TEXTURE_CUBE_MAP;
				}
				else if (_strcmpi(scan_buffer, "FILE") == 0)
				{
					ScanString(buffer, pTexture->m_fileTexture[index], iStart);
					index++;
				}
				else if (_strcmpi(scan_buffer, "WRAP") == 0)
				{
					ScanString(buffer, scan_buffer, iStart);
					if (_strcmpi(scan_buffer, "GL_CLAMP_TO_EDGE") != 0)
						pTexture->m_wrap = GL_REPEAT;
					else
						pTexture->m_wrap = GL_CLAMP_TO_EDGE;
				}
				else if (_strcmpi(scan_buffer, "FILTER") == 0)
				{
					ScanString(buffer, scan_buffer, iStart);
					if (_strcmpi(scan_buffer, "GL_LINEAR") != 0)
						pTexture->m_filter = GL_NEAREST;
					else
						pTexture->m_filter = GL_LINEAR;
				}
			}
		}
	}

	fclose(pFile);
}

void* cResourceManager::GetResourceByID(int rmType, int rmID)
{
	void *pResult = NULL;

	switch(rmType)
	{
		case RM_SHADER:
			{
				for (unsigned int i=0; i<m_vShaders.size(); i++)
				{
					if (m_vShaders[i]->m_ID == rmID)
					{
						pResult = m_vShaders[i];
						break;
					}
				}
			}
			break;

		case RM_MODEL:
			{
				for (unsigned int i=0; i<m_vModels.size(); i++)
				{
					if (m_vModels[i]->m_ID == rmID)
					{
						pResult = m_vModels[i];
						break;
					}
				}
			}
			break;

		case RM_TEXTURE:
			{
				for (unsigned int i=0; i<m_vTextures.size(); i++)
				{
					if (m_vTextures[i]->m_ID == rmID)
					{
						pResult = m_vTextures[i];
						break;
					}
				}
			}
			break;

		default:
			break;
	}

	return pResult;
}
